#ifndef POOLALLOCATOR_H_INCLUDED
#define POOLALLOCATOR_H_INCLUDED

#include "Atomic.h"
#include "StackAllocator.h"

namespace CEngine
{

namespace MemoryManager {
    void initialize(void);
}

//
///WARNING! DO NOT USE WITH ELEMENTS SMALLER THAN 8 BYTES!
//
class PoolAllocator {
    public:

        ///Create a pool with the given number of elements of the given size.
        PoolAllocator(U64 sizeOfElement, U64 numberOfElements);

        ///Create an aligned pool with the given number of elements of the given size.
        ///ONLY ALIGNS THE FIRST ELEMENT AND ASSUMES THE REST WILL ALSO BE ALIGNED
        PoolAllocator(U64 sizeOfElement, U64 numberOfElements, U64 alignment);

        ///Destroys the pool.
        ~PoolAllocator(void);

        ///Allocates a free element.
        void*
        alloc(void);

        ///Frees the given element.
        void
        free(void* pointer);

        ///Returns the number of free elements.
        U64
        getFreeElements(void);

        ///Returns the total number of elements.
        U64
        getTotalElements(void);

        ///Returns the size of elements.
        U64
        getElementSize(void);

        ///Resets the pool.
        void
        clear(void);

        friend void MemoryManager::initialize(void);

    private:

        void*               poolPointer;
        void*               nextElementPointer;
        U64                 freeElements, totalElements;
        U64                 elementSize;
};

inline U64
PoolAllocator::getFreeElements(void) {
    return freeElements;
}

inline U64
PoolAllocator::getTotalElements(void) {
    return totalElements;
}

inline U64
PoolAllocator::getElementSize(void) {
    return elementSize;
}

}

#endif // POOLALLOCATOR_H_INCLUDED
